package com.moonlight.demo;

import java.net.InetSocketAddress;
import java.nio.charset.Charset;

import org.apache.mina.core.session.IdleStatus;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.filter.codec.textline.LineDelimiter;
import org.apache.mina.filter.codec.textline.TextLineCodecFactory;
import org.apache.mina.filter.keepalive.KeepAliveFilter;
import org.apache.mina.filter.keepalive.KeepAliveMessageFactory;
import org.apache.mina.filter.keepalive.KeepAliveRequestTimeoutHandler;
import org.apache.mina.transport.socket.nio.NioSocketAcceptor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;

import com.moonlight.demo.custom.Consts;
import com.moonlight.demo.custom.CustomEncodingFactory;
import com.moonlight.demo.custom.CustomPackage;
import com.moonlight.mina.MinaEncodingFactory;
import com.moonlight.mina.MinaHandler;

/**
 * 心跳机制
 * @author smartlab
 *
 */
@Component
public class Server implements CommandLineRunner {
	private final static Logger logger = LoggerFactory.getLogger(Server.class);
	
	// 端口号
	private final static int port = 3000;
	
	// 心跳最大连接时间
	private static final int idle_time = 20;
	
	// 心跳发送间隔
	private static final int heart_beat = 15;
	
	// 心跳发送包内容
	private static final String requestContent = "heart_request";
	
	// 心跳接受包内容
	private static final String responseContent = "heart_response";

	@Override
	public void run(String... args) throws Exception {
		NioSocketAcceptor acceptor = new NioSocketAcceptor();
		acceptor.getSessionConfig().setReadBufferSize(1024);
		acceptor.getSessionConfig().setIdleTime(IdleStatus.WRITER_IDLE , idle_time);
		acceptor.getFilterChain().addLast("codec" , new ProtocolCodecFilter(new CustomEncodingFactory(Charset.forName("utf-8"))));
		KeepAliveMessageFactory factory = new KeepAliveMessageFactoryImpl();
		KeepAliveRequestTimeoutHandler timeoutHandler = new KeepAliveRequestTimeoutHandlerImpl();
		// 心跳检测过滤器，服务端只关心写空闲
		KeepAliveFilter filter = new KeepAliveFilter(factory , IdleStatus.WRITER_IDLE , timeoutHandler);
		filter.setForwardEvent(true);
		filter.setRequestInterval(heart_beat);
		acceptor.getFilterChain().addLast("alive" , filter);
		acceptor.setHandler(new MinaHandler());
		acceptor.bind(new InetSocketAddress(port));
		logger.info("端口3000已经打开");
	}
	
	private class KeepAliveMessageFactoryImpl implements KeepAliveMessageFactory {

		@Override
		public boolean isRequest(IoSession session, Object message) {
			// TODO Auto-generated method stub
			CustomPackage package1 = (CustomPackage) message;
			if(package1.getContent().toString().equals(requestContent)) {
				logger.info("服务端接受心跳");
				return true;
			} else {
				return false;
			}
		}

		@Override
		public boolean isResponse(IoSession session, Object message) {
			// 客户端不会给服务端响应
			return false;
		}

		@Override
		public Object getRequest(IoSession session) {
			// TODO Auto-generated method stub
			return null;
		}

		@Override
		public Object getResponse(IoSession session, Object request) {
			// TODO Auto-generated method stub
			// 服务端返回响应
			logger.info("服务端返回响应");
			CustomPackage package1 = new CustomPackage(Consts.HEART, responseContent);
			return package1;
		}
		
	}
}
